// 线程安全的观察者模式实现。
// 但不支持主动调用 Unregister 若在 Update 中调用 Unregister 会死锁。
#include <muduo/base/Mutex.h>
#include <boost/enable_shared_from_this.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <algorithm>
#include <vector>
#include <stdio.h>

class Observable;

class Observer : public boost::enable_shared_from_this<Observer> {
public:	
	virtual ~Observer();
	virtual void Update() = 0;

	void Observe(Observable *s);

protected:
	// Observable *_subject;
};

class Observable {
public:
	void Register(boost::weak_ptr<Observer> x) {
		_observers.push_back(x); // 这里也应该加锁吧，作者未在这里加锁。
	}

	// void Unregister(Observer *x) {
	// 	std::vector<Observer*>::iterator it = std::find(_observers.begin(), _observers.end(), x);
	// 	if (it != _observers.end()) {
	// 		std::swap(*it, _observers.back());
	// 		_observers.pop_back();
	// 	}
	// }

	void NotifyObservers() {
		muduo::MutexLockGuard lock(_mutex);
		Iterator it = _observers.begin();
		while (it != _observers.end()) {
			boost::shared_ptr<Observer> obj(it->lock());
			if (obj) {
				obj->Update();
				++it;
			} else {
				printf("NotifyObservers erase\n");
				it = _observers.erase(it);
			}
		}
	}

private:
	typedef std::vector<boost::weak_ptr<Observer> >::iterator Iterator;

	mutable muduo::MutexLock _mutex;
	std::vector<boost::weak_ptr<Observer> > _observers;
};

Observer::~Observer() {
	// _subject->Unregister(this);
}

void
Observer::Observe(Observable *s) {
	s->Register(shared_from_this());
	// _subject = s;
}

class Foo : public Observer {
	virtual void Update() {
		printf("Foo::Update %p\n", this);
	}
};

int 
main() {
	Observable subject;
	{
		boost::shared_ptr<Foo> p(new Foo);
		p->Observe(&subject);
		subject.NotifyObservers(); // 之后 Foo 对象被析构，从观察者中被移除。
	}
	subject.NotifyObservers();
	return 0;
}
